#include<iostream>
#include<pthread.h>
#include<vector>
#include<time.h>
#include<unistd.h>
#define NUMBER 5
#define CAPACITY 10
class WaitQueue{
  private:
    std::vector<int> _commodeity;
    int _capacity = CAPACITY;
  public:
    pthread_mutex_t _PCMutex;
    pthread_cond_t _full;
    pthread_cond_t _empty;
  public:
    WaitQueue()
    {
      _commodeity.reserve(_capacity);
    pthread_mutex_init(&_PCMutex,nullptr);
    pthread_cond_init(&_full,nullptr);
    pthread_cond_init(&_empty,nullptr);
    }
    ~WaitQueue()
    {
    pthread_mutex_destroy(&_PCMutex);
    pthread_cond_destroy(&_full);
    pthread_cond_destroy(&_empty);
    }
  public:
    void PLock()
    {
      pthread_mutex_lock(&_PCMutex);
    }
    void PUnlock()
    {
      pthread_mutex_unlock(&_PCMutex);
    }
    bool IsEmpty()
    {
      return _commodeity.size() == _capacity;
    }
    bool IsFull()
    {
      return _commodeity.size() == 0;
    }
    
    void sell(void* args)
    {
      PLock();
      int data = *(int*)args;
      delete (int*)args;
      if(IsEmpty())
      {
        pthread_cond_wait(&_empty,&_PCMutex);
      }
      else{
        _commodeity.push_back(data);
        std::cout << "生产" << pthread_self() << " : " << data << std::endl;
        if(_commodeity.size() > _capacity/2)
        {
          pthread_cond_signal(&_full);
        }
      }
      PUnlock();
    }
    void buy()
    {
      PLock();
      if(IsFull())
      {
        pthread_cond_wait(&_full,&_PCMutex);
      }
      else{
        int data = _commodeity[_commodeity.size()-1];
        _commodeity.pop_back();
        std::cout << "消费" << pthread_self() << " : " << data << std::endl;
        if(_commodeity.size() < _capacity/2)
        {
          pthread_cond_signal(&_empty);
        }
      }
      PUnlock();
    }
};
void* Sell(void* args)
{
  WaitQueue& q = *(WaitQueue*)args;
  while(true)
  {
    int *data = new int(rand()%100);
    q.sell((void*)data);
  }

  return nullptr;
}
void* Buy(void* args)
{
  WaitQueue& q = *(WaitQueue*)args;
  while(true)
  {
    q.buy();
    //sleep(1);
  }
  return nullptr;
}
int main()
{
  srand((long long)time(0));
  WaitQueue q;
  pthread_t shop;
  pthread_t people[NUMBER];
  if(pthread_create(&shop,nullptr,Sell,(void*)&q) != 0)
  {
    perror("shop create is error");
  }
  for(int i = 0;i < NUMBER;i++)
  {
    pthread_create(people+i,nullptr,Buy,(void*)&q);
  }

  pthread_join(shop,nullptr);
  for(int i = 0;i < NUMBER;i++)
  {
    pthread_join(people[i],nullptr);
  }
  

  return 0;
}
